package com.bi.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bi.entity.ChartComponent;
import com.bi.entity.DataComponent;
import com.bi.entity.WideTable;
import com.bi.mapper.ChartComponentMapper;
import com.bi.service.ChartComponentService;
import com.bi.service.DataComponentService;
import com.bi.service.WideTableService;
import com.bi.vo.WideTableVO;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 图表组件服务实现类
 * 
 * @author BI Platform Team
 * @since 1.0.0
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ChartComponentServiceImpl extends ServiceImpl<ChartComponentMapper, ChartComponent> implements ChartComponentService {

    private final DataComponentService dataComponentService;
    private final WideTableService wideTableService;
    private final RedisTemplate<String, Object> redisTemplate;

    private static final String CHART_CACHE_KEY = "chart_component:";
    private static final String CHART_DATA_CACHE_KEY = "chart_data:";

    @Override
    public IPage<ChartComponent> getChartComponentPage(long current, long size, Map<String, Object> params) {
        Page<ChartComponent> page = new Page<>(current, size);
        return baseMapper.selectChartComponentPage(page, params);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean createChartComponent(ChartComponent chartComponent) {
        try {
            // 设置创建时间
            chartComponent.setCreateTime(LocalDateTime.now());
            chartComponent.setUpdateTime(LocalDateTime.now());
            
            // 保存图表组件
            boolean saveResult = save(chartComponent);
            if (!saveResult) {
                return false;
            }

            // 清除相关缓存
            clearChartCache(chartComponent.getId());

            log.info("创建图表组件成功: id={}, name={}", chartComponent.getId(), chartComponent.getName());
            return true;

        } catch (Exception e) {
            log.error("创建图表组件失败: name={}, error={}", chartComponent.getName(), e.getMessage(), e);
            throw new RuntimeException("创建图表组件失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateChartComponent(ChartComponent chartComponent) {
        try {
            // 设置更新时间
            chartComponent.setUpdateTime(LocalDateTime.now());
            
            // 更新图表组件
            boolean updateResult = updateById(chartComponent);
            if (!updateResult) {
                return false;
            }

            // 清除相关缓存
            clearChartCache(chartComponent.getId());

            log.info("更新图表组件成功: id={}, name={}", chartComponent.getId(), chartComponent.getName());
            return true;

        } catch (Exception e) {
            log.error("更新图表组件失败: id={}, error={}", chartComponent.getId(), e.getMessage(), e);
            throw new RuntimeException("更新图表组件失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteChartComponent(Long id) {
        try {
            // 删除图表组件
            boolean deleteResult = removeById(id);
            
            // 清除缓存
            clearChartCache(id);
            
            log.info("删除图表组件成功: id={}", id);
            return deleteResult;

        } catch (Exception e) {
            log.error("删除图表组件失败: id={}, error={}", id, e.getMessage(), e);
            throw new RuntimeException("删除图表组件失败: " + e.getMessage());
        }
    }

    @Override
    public List<ChartComponent> getChartComponentsByType(String chartType) {
        return baseMapper.selectByChartType(chartType);
    }

    @Override
    public Map<String, Object> getChartStatistics() {
        return baseMapper.selectChartStatistics();
    }

    @Override
    public Map<String, Object> testChartDataSource(ChartComponent chartComponent) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            switch (chartComponent.getDataSourceType()) {
                case WIDE_TABLE:
                    result = testWideTableDataSource(chartComponent);
                    break;
                case DATA_COMPONENT:
                    result = testDataComponentDataSource(chartComponent);
                    break;
                case ELASTICSEARCH:
                    result = testElasticsearchDataSource(chartComponent);
                    break;
                case API:
                    result = testApiDataSource(chartComponent);
                    break;
                case DATABASE:
                    result = testDatabaseDataSource(chartComponent);
                    break;
                default:
                    result.put("success", false);
                    result.put("message", "不支持的数据源类型");
            }
        } catch (Exception e) {
            log.error("测试图表数据源失败: type={}, error={}", chartComponent.getDataSourceType(), e.getMessage());
            result.put("success", false);
            result.put("message", "测试失败: " + e.getMessage());
        }
        
        return result;
    }

    @Override
    public Map<String, Object> getChartData(Long componentId, Map<String, Object> params) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 检查缓存
            String cacheKey = CHART_DATA_CACHE_KEY + componentId + ":" + params.hashCode();
            Object cachedData = redisTemplate.opsForValue().get(cacheKey);
            if (cachedData instanceof Map) {
                @SuppressWarnings("unchecked")
                Map<String, Object> resultMap = (Map<String, Object>) cachedData;
                return resultMap;
            }

            // 获取图表组件配置
            ChartComponent chartComponent = getById(componentId);
            if (chartComponent == null) {
                result.put("success", false);
                result.put("message", "图表组件不存在");
                return result;
            }

            // 执行查询
            switch (chartComponent.getDataSourceType()) {
                case WIDE_TABLE:
                    result = executeWideTableQuery(chartComponent, params);
                    break;
                case DATA_COMPONENT:
                    result = executeDataComponentQuery(chartComponent, params);
                    break;
                case ELASTICSEARCH:
                    result = executeElasticsearchQuery(chartComponent, params);
                    break;
                case API:
                    result = executeApiQuery(chartComponent, params);
                    break;
                case DATABASE:
                    result = executeDatabaseQuery(chartComponent, params);
                    break;
                default:
                    result.put("success", false);
                    result.put("message", "不支持的数据源类型");
            }

            // 缓存结果
            if ((Boolean) result.getOrDefault("success", false)) {
                int cacheTime = chartComponent.getRefreshInterval() != null ? chartComponent.getRefreshInterval() : 30;
                redisTemplate.opsForValue().set(cacheKey, result, cacheTime, TimeUnit.MINUTES);
            }

        } catch (Exception e) {
            log.error("获取图表数据失败: componentId={}, error={}", componentId, e.getMessage(), e);
            result.put("success", false);
            result.put("message", "获取数据失败: " + e.getMessage());
        }

        return result;
    }

    @Override
    public Map<String, Object> previewChartData(ChartComponent chartComponent, Map<String, Object> params) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 限制预览数据量
            params.put("limit", 100);

            switch (chartComponent.getDataSourceType()) {
                case WIDE_TABLE:
                    result = executeWideTableQuery(chartComponent, params);
                    break;
                case DATA_COMPONENT:
                    result = executeDataComponentQuery(chartComponent, params);
                    break;
                case ELASTICSEARCH:
                    result = executeElasticsearchQuery(chartComponent, params);
                    break;
                case API:
                    result = executeApiQuery(chartComponent, params);
                    break;
                case DATABASE:
                    result = executeDatabaseQuery(chartComponent, params);
                    break;
                default:
                    result.put("success", false);
                    result.put("message", "不支持的数据源类型");
            }

        } catch (Exception e) {
            log.error("预览图表数据失败: error={}", e.getMessage(), e);
            result.put("success", false);
            result.put("message", "预览失败: " + e.getMessage());
        }

        return result;
    }

    @Override
    public boolean refreshChartCache(Long componentId) {
        try {
            clearChartCache(componentId);
            log.info("刷新图表缓存成功: componentId={}", componentId);
            return true;
        } catch (Exception e) {
            log.error("刷新图表缓存失败: componentId={}, error={}", componentId, e.getMessage());
            return false;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ChartComponent copyChartComponent(Long componentId, String newName) {
        try {
            // 获取原图表组件
            ChartComponent sourceComponent = getById(componentId);
            if (sourceComponent == null) {
                throw new RuntimeException("源图表组件不存在");
            }

            // 创建新图表组件
            ChartComponent newComponent = new ChartComponent();
            newComponent.setName(newName);
            newComponent.setDisplayName(sourceComponent.getDisplayName() + "_副本");
            newComponent.setDescription(sourceComponent.getDescription());
            newComponent.setChartType(sourceComponent.getChartType());
            newComponent.setDataSourceType(sourceComponent.getDataSourceType());
            newComponent.setDataSourceConfig(sourceComponent.getDataSourceConfig());
            newComponent.setWideTableId(sourceComponent.getWideTableId());
            newComponent.setDataComponentId(sourceComponent.getDataComponentId());
            newComponent.setSqlQuery(sourceComponent.getSqlQuery());
            newComponent.setEsQuery(sourceComponent.getEsQuery());
            newComponent.setChartConfig(sourceComponent.getChartConfig());
            newComponent.setDataConfig(sourceComponent.getDataConfig());
            newComponent.setStyleConfig(sourceComponent.getStyleConfig());
            newComponent.setInteractionConfig(sourceComponent.getInteractionConfig());
            newComponent.setCacheConfig(sourceComponent.getCacheConfig());
            newComponent.setRefreshInterval(sourceComponent.getRefreshInterval());
            newComponent.setStatus(ChartComponent.ComponentStatus.DRAFT);
            newComponent.setCreator(sourceComponent.getCreator());

            boolean saveResult = save(newComponent);
            if (!saveResult) {
                throw new RuntimeException("保存新图表组件失败");
            }

            log.info("复制图表组件成功: sourceId={}, newId={}, newName={}", componentId, newComponent.getId(), newName);
            return newComponent;

        } catch (Exception e) {
            log.error("复制图表组件失败: componentId={}, newName={}, error={}", componentId, newName, e.getMessage(), e);
            throw new RuntimeException("复制图表组件失败: " + e.getMessage());
        }
    }

    @Override
    public Map<String, Object> generateChartTemplate(String chartType, Map<String, Object> dataConfig) {
        Map<String, Object> template = new HashMap<>();
        
        try {
            // 根据图表类型生成基础配置模板
            switch (chartType.toUpperCase()) {
                case "LINE":
                    template = generateLineChartTemplate(dataConfig);
                    break;
                case "BAR":
                    template = generateBarChartTemplate(dataConfig);
                    break;
                case "PIE":
                    template = generatePieChartTemplate(dataConfig);
                    break;
                case "SCATTER":
                    template = generateScatterChartTemplate(dataConfig);
                    break;
                default:
                    template = generateDefaultChartTemplate(dataConfig);
            }
            
            template.put("success", true);
            log.info("生成图表配置模板成功: chartType={}", chartType);
            
        } catch (Exception e) {
            log.error("生成图表配置模板失败: chartType={}, error={}", chartType, e.getMessage());
            template.put("success", false);
            template.put("message", "生成模板失败: " + e.getMessage());
        }
        
        return template;
    }

    @Override
    public Map<String, Object> validateChartConfig(Map<String, Object> chartConfig) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 基础验证
            if (chartConfig == null || chartConfig.isEmpty()) {
                result.put("valid", false);
                result.put("message", "图表配置不能为空");
                return result;
            }
            
            // 验证必要字段
            if (!chartConfig.containsKey("type")) {
                result.put("valid", false);
                result.put("message", "缺少图表类型配置");
                return result;
            }
            
            result.put("valid", true);
            result.put("message", "配置验证通过");
            
        } catch (Exception e) {
            log.error("验证图表配置失败: error={}", e.getMessage());
            result.put("valid", false);
            result.put("message", "验证失败: " + e.getMessage());
        }
        
        return result;
    }

    @Override
    public Map<String, Object> exportChart(Long componentId, String format, Map<String, Object> params) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 简化实现，实际需要调用图表渲染服务
            result.put("success", true);
            result.put("message", "导出功能开发中");
            result.put("format", format);
            result.put("downloadUrl", "/api/charts/" + componentId + "/export/" + format);
            
        } catch (Exception e) {
            log.error("导出图表失败: componentId={}, format={}, error={}", componentId, format, e.getMessage());
            result.put("success", false);
            result.put("message", "导出失败: " + e.getMessage());
        }
        
        return result;
    }

    @Override
    public List<Map<String, Object>> getPopularChartTypes(Integer limit) {
        return baseMapper.selectPopularChartTypes(limit != null ? limit : 10);
    }

    // 私有方法实现

    private Map<String, Object> testWideTableDataSource(ChartComponent chartComponent) {
        Map<String, Object> result = new HashMap<>();
        
        if (chartComponent.getWideTableId() == null) {
            result.put("success", false);
            result.put("message", "宽表ID不能为空");
            return result;
        }

        WideTableVO wideTable = wideTableService.getWideTableById(chartComponent.getWideTableId());
        if (wideTable == null) {
            result.put("success", false);
            result.put("message", "宽表不存在");
            return result;
        }

        result.put("success", true);
        result.put("message", "宽表连接正常");
        return result;
    }

    private Map<String, Object> testDataComponentDataSource(ChartComponent chartComponent) {
        Map<String, Object> result = new HashMap<>();
        
        if (chartComponent.getDataComponentId() == null) {
            result.put("success", false);
            result.put("message", "数据组件ID不能为空");
            return result;
        }

        DataComponent dataComponent = dataComponentService.getById(chartComponent.getDataComponentId());
        if (dataComponent == null) {
            result.put("success", false);
            result.put("message", "数据组件不存在");
            return result;
        }

        result.put("success", true);
        result.put("message", "数据组件连接正常");
        return result;
    }

    private Map<String, Object> testElasticsearchDataSource(ChartComponent chartComponent) {
        Map<String, Object> result = new HashMap<>();
        result.put("success", true);
        result.put("message", "ES连接测试成功");
        return result;
    }

    private Map<String, Object> testApiDataSource(ChartComponent chartComponent) {
        Map<String, Object> result = new HashMap<>();
        result.put("success", true);
        result.put("message", "API连接测试成功");
        return result;
    }

    private Map<String, Object> testDatabaseDataSource(ChartComponent chartComponent) {
        Map<String, Object> result = new HashMap<>();
        result.put("success", true);
        result.put("message", "数据库连接测试成功");
        return result;
    }

    private Map<String, Object> executeWideTableQuery(ChartComponent chartComponent, Map<String, Object> params) {
        // 简化实现，实际应该根据配置查询宽表数据
        Map<String, Object> result = new HashMap<>();
        result.put("success", true);
        result.put("data", List.of());
        return result;
    }

    private Map<String, Object> executeDataComponentQuery(ChartComponent chartComponent, Map<String, Object> params) {
        // 调用数据组件服务获取数据
        try {
            return dataComponentService.executeQuery(chartComponent.getDataComponentId(), params);
        } catch (Exception e) {
            Map<String, Object> result = new HashMap<>();
            result.put("success", false);
            result.put("message", "数据组件查询失败: " + e.getMessage());
            return result;
        }
    }

    private Map<String, Object> executeElasticsearchQuery(ChartComponent chartComponent, Map<String, Object> params) {
        Map<String, Object> result = new HashMap<>();
        result.put("success", true);
        result.put("data", List.of());
        return result;
    }

    private Map<String, Object> executeApiQuery(ChartComponent chartComponent, Map<String, Object> params) {
        Map<String, Object> result = new HashMap<>();
        result.put("success", true);
        result.put("data", List.of());
        return result;
    }

    private Map<String, Object> executeDatabaseQuery(ChartComponent chartComponent, Map<String, Object> params) {
        Map<String, Object> result = new HashMap<>();
        result.put("success", true);
        result.put("data", List.of());
        return result;
    }

    private Map<String, Object> generateLineChartTemplate(Map<String, Object> dataConfig) {
        Map<String, Object> template = new HashMap<>();
        template.put("type", "line");
        template.put("title", Map.of("text", "折线图"));
        template.put("xAxis", Map.of("type", "category"));
        template.put("yAxis", Map.of("type", "value"));
        template.put("series", List.of(Map.of("type", "line")));
        return template;
    }

    private Map<String, Object> generateBarChartTemplate(Map<String, Object> dataConfig) {
        Map<String, Object> template = new HashMap<>();
        template.put("type", "bar");
        template.put("title", Map.of("text", "柱状图"));
        template.put("xAxis", Map.of("type", "category"));
        template.put("yAxis", Map.of("type", "value"));
        template.put("series", List.of(Map.of("type", "bar")));
        return template;
    }

    private Map<String, Object> generatePieChartTemplate(Map<String, Object> dataConfig) {
        Map<String, Object> template = new HashMap<>();
        template.put("type", "pie");
        template.put("title", Map.of("text", "饼图"));
        template.put("series", List.of(Map.of("type", "pie", "radius", "50%")));
        return template;
    }

    private Map<String, Object> generateScatterChartTemplate(Map<String, Object> dataConfig) {
        Map<String, Object> template = new HashMap<>();
        template.put("type", "scatter");
        template.put("title", Map.of("text", "散点图"));
        template.put("xAxis", Map.of("type", "value"));
        template.put("yAxis", Map.of("type", "value"));
        template.put("series", List.of(Map.of("type", "scatter")));
        return template;
    }

    private Map<String, Object> generateDefaultChartTemplate(Map<String, Object> dataConfig) {
        Map<String, Object> template = new HashMap<>();
        template.put("type", "line");
        template.put("title", Map.of("text", "默认图表"));
        return template;
    }

    private void clearChartCache(Long componentId) {
        // 清除图表缓存
        redisTemplate.delete(CHART_CACHE_KEY + componentId);
        
        // 清除数据缓存（模糊匹配）
        String pattern = CHART_DATA_CACHE_KEY + componentId + ":*";
        redisTemplate.delete(redisTemplate.keys(pattern));
    }
}